# -*- coding: utf-8 -*-
import networkx as nx
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import json
import sys
from math import sqrt

class DegreeCalculate:
    def __init__(self, anagraphs, algorithmType):
        self.result_dict = {}
        self.algorithmType = algorithmType
        self.anagraphs = anagraphs
        self.anagraphs = self.__reshapeData(self.anagraphs)

    def __reshapeData(self, anagraph_data):
        for item_ana in anagraph_data:
            tmp_vector = np.array(item_ana['vector'])
            tmp_vector = tmp_vector.reshape(1, tmp_vector.size)
            item_ana['vector'] = list(tmp_vector[0])

        return anagraph_data

    def setGate(self, gate):
        self.distance_gate = gate

    def __getDistance(self, vector_1, vector_2):
        if self.algorithmType == 1:
            vec_1 = np.array(vector_1['vector'])
            vec_2 = np.array(vector_2['vector'])

            # 1.euclidean distance
            distance = np.sqrt(np.sum(np.square(vec_1 - vec_2)))
        elif self.algorithmType == 2:
            vec_1 = np.array(vector_1['vector'])
            vec_2 = np.array(vector_2['vector'])

            # 2.cosine similarity
            distance = 1.0 - (vec_1.dot(vec_2)) / ((np.sqrt(vec_1.dot(vec_1))) * (np.sqrt(vec_2.dot(vec_2))))
        elif self.algorithmType == 3:
            # 3.Jaccard distance
            insect_names    = list(set(vector_1['medicines']) & set(vector_2['medicines']))
            union_names     = list(set(vector_1['medicines']) | set(vector_2['medicines']))

            distance        = 1.0 - float(len(insect_names)) / len(union_names)
        elif self.algorithmType == 4:
            # 4. pearson correlation coefficient
            vec_1 = vector_1['vector']
            vec_2 = vector_2['vector']

            length = len(vec_1)

            sum1 = sum(vec_1)
            sum2 = sum(vec_2)

            sqSum1 = sum([pow(item_1, 2) for item_1 in vec_1])
            sqSum2 = sum([pow(item_2, 2) for item_2 in vec_2])

            pSum = sum([vec_1[index] * vec_2[index] for index in range(len(vec_1))])

            num = pSum - (sum1 * sum2 / length)
            den = sqrt((sqSum1 - pow(sum1, 2) / length) * (sqSum2 - pow(sum2, 2) / length))

            if den == 0:
                distance = 1.0
            else :
                distance = 1.0 - num / den
        else:
            print 'set algorithm type error, make sure value in [1(euclidean distance), 2(cosine similarity), 3(degree),]' + '\n'

        return 1.0 - distance

    def calculateOrigin(self):
        name_list       = []
        # self.distance_gate   = 0.4

        distance_dict = {}

        for vector_1 in self.anagraphs:
            name_list.append(vector_1['name'])

            distance_dict[vector_1['name']] = []

            for vector_2 in self.anagraphs:
                if vector_2['name'] not in name_list:
                    # get distance
                    distance = self.__getDistance(vector_1, vector_2)
                    if distance <= self.distance_gate:
                        distance_dict[vector_1['name']].append(distance)

        self.result_dict = {}
        for (ana_name, dis_list) in distance_dict.items():
            self.result_dict[ana_name] = sum(dis_list)

    def calculateCluster(self, ana_dict):
        distance_dict = {}

        for (ana_name, ana_list) in ana_dict.items():
            name_list = []
            if len(ana_list) > 0:
                for vector_1 in self.anagraphs:
                    name_list.append(vector_1['name'])

                    distance_dict[vector_1['name']] = []

                    for vector_2 in self.anagraphs:
                        # tmp_name_1 = vector_1['name']
                        # tmp_name_2 = vector_2['name']

                        if vector_2['name'] not in name_list and vector_1['name'] in ana_list and vector_2['name'] in ana_list:
                            # get distance
                            distance = self.__getDistance(vector_1, vector_2)
                            if distance <= self.distance_gate:
                                distance_dict[vector_1['name']].append(distance)

        self.result_dict = {}
        for (ana_name, dis_list) in distance_dict.items():
            if (len(dis_list) > 0):
                self.result_dict[ana_name] = sum(dis_list)

    def exportData(self, filename):
        fp = open(filename, 'w')
        result_dict = json.dumps(self.result_dict)
        fp.write(result_dict)
        fp.close()
